package com.gonsin.ta.logic.process;

import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gonsin.ta.logic.enums.ComponentTypeEnum;
import com.gonsin.ta.logic.enums.ConditionTypeEnum;
import com.gonsin.ta.logic.enums.NodeTypeEnum;
import com.gonsin.ta.logic.exceptions.TaException;
import com.gonsin.ta.logic.node.Node;
import com.gonsin.ta.logic.node.SignalNodeAdapter;
import com.gonsin.ta.logic.parse.Constant;
import com.gonsin.ta.logic.parse.condition.Executable;
import com.gonsin.ta.logic.parse.condition.RunCondition;
import com.gonsin.ta.logic.parse.condition.SwitchCondition;
import com.gonsin.ta.logic.parse.condition.WaitCondition;
import com.gonsin.ta.logic.parse.serialize.DeserializeContext;
import com.gonsin.ta.logic.parse.serialize.DeserializeTypeAdapter;
import com.gonsin.ta.logic.parse.serialize.TaDeserializable;
import com.gonsin.ta.logic.parse.serialize.TaSerializable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.bytebuddy.description.method.MethodDescription;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 节点序列化和反序列化工具
 */
public class ExecutableSerializeHelper {

    public static List<Executable> createExecutableFromJson(String exeJson, String stackJson, SignalCenter signalCenter) {
        Assert.isTrue(JSONUtil.isJson(exeJson));

        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(TaDeserializable.class, new DeserializeTypeAdapter());
        Gson gson = gsonBuilder.create();

        Map<String, TaDeserializable> stack = stackJson == null ? new HashMap<>() : gson.fromJson(stackJson, new TypeToken<Map<String, TaDeserializable>>(){}.getType());

        // TODO

        DeserializeContext context = new DeserializeContext();
        context.setSignalCenter(signalCenter);
        context.readyStack(stack);
        List<TaDeserializable> serializables = (List<TaDeserializable>) gson.fromJson(exeJson, new TypeToken<List<TaDeserializable>>(){}.getType());

        return serializables.stream().map(serial -> serial.toExecutable(context)).collect(Collectors.toList());


//        JSONArray array = JSONUtil.parseArray(json);
//        List<Executable> executables = new ArrayList<>();
//        array.forEach(j -> {
//            if(j instanceof JSONObject){
//
//                // 如果是condition类型
//                String componentType = ((JSONObject) j).get(Constant.COMPONENT_TYPE, String.class);
//                ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.getEnumByCode(componentType);
//                if(componentTypeEnum == null){
//                    return;
//                }
//                switch (componentTypeEnum){
//                    case CONDITION:
//                        executables.add(createCondition((JSONObject) j, signalCenter));
//                        break;
//                    case NODE:
//                        executables.add(createNode((JSONObject) j));
//                        break;
//                }
//            }
//        });
//        return executables;
    }

//    public static Executable createNode(JSONObject jsonObject) {
//        String nodeId = jsonObject.getStr(Constant.NODE_ID);
//        Node node = TaBus.getNode(nodeId);
//        if(node == null){
//            throw new TaException("反序列化失败，未找到nodeId=【{}】的节点", nodeId);
//        }
//        return node;
//    }
//
//    public static Executable createCondition(JSONObject jsonObject, SignalCenter signalCenter) {
//
//        String conditionType = jsonObject.get(Constant.CONDITION_TYPE, String.class);
//        ConditionTypeEnum conditionTypeEnum = ConditionTypeEnum.getEnumByCode(conditionType);
//        if(conditionTypeEnum == null){
//            throw new TaException("反序列化失败，json内容为【{}】", jsonObject.toString());
//        }
//
//        switch (conditionTypeEnum){
//
//            // 运行方法
//            case RUN:
//            {
//                RunCondition runCondition = new RunCondition();
//                JSONArray executableArray = jsonObject.getJSONArray("executableList");
//                List<Executable> executables = parseExecutableList(executableArray, signalCenter);
//                for(Executable e : executables){
//                    runCondition.addExecutable(e);
//                }
//                return runCondition;
//            }
//            case WAIT:
//            {
//                String signalNode = jsonObject.getStr("signalNode");
//                Long timeout = jsonObject.getLong("timeout");
//                JSONArray next = jsonObject.getJSONArray("next");
//                JSONArray timeoutTask = jsonObject.getJSONArray("timeoutTask");
//
//
//                Node node = TaBus.getNode(signalNode);
//                if(node == null){
//                    throw new TaException("反序列化失败，找不到信号节点【{}】，json内容为【{}】", signalNode, jsonObject.toString());
//                }
//                if(node.getNodeType() != NodeTypeEnum.SIGNAL){
//                    throw new TaException("反序列化失败，【{}】节点不是信号节点，json内容为【{}】", signalNode, jsonObject.toString());
//                }
//
//                WaitCondition waitCondition = new WaitCondition((SignalNodeAdapter) node, timeout, signalCenter);
//                waitCondition.setNext(parseExecutableList(next, signalCenter));
//                if(timeoutTask != null){
//                    waitCondition.setTimeoutTask(parseExecutableList(timeoutTask, signalCenter));
//                }
//
//                return waitCondition;
//            }
//            case SWITCH: {
//
//                String signalNode = jsonObject.getStr("switchNode");
//                Node node = TaBus.getNode(signalNode);
//                if(node == null){
//                    throw new TaException("反序列化失败，找不到选择节点【{}】，json内容为【{}】", signalNode, jsonObject.toString());
//                }
//                if(node.getNodeType() != NodeTypeEnum.SWITCH){
//                    throw new TaException("反序列化失败，【{}】节点不是选择节点，json内容为【{}】", signalNode, jsonObject.toString());
//                }
//                SwitchCondition switchCondition = new SwitchCondition(node);
//
//                JSONObject switchMap = jsonObject.getJSONObject("switchMap");
//                switchMap.entrySet().forEach((keyValue) -> {
//                    JSONArray v = (JSONArray) keyValue.getValue();
//                    String result = keyValue.getKey();
//                    switchCondition.putCase(result, parseExecutableList(v, signalCenter));
//                });
//
//                return switchCondition;
//            }
//        }
//        throw new TaException("反序列化失败，未找到conditionType=【{}】的解析方式", conditionType);
//    }
//
//    public static List<Executable> parseExecutableList(JSONArray executableArray, SignalCenter signalCenter) {
//        List<Executable> executables = new ArrayList<>();
//        executableArray.forEach(j -> {
//            // 如果是condition类型
//            String componentType = ((JSONObject) j).get(Constant.COMPONENT_TYPE, String.class);
//            ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.getEnumByCode(componentType);
//            if(componentTypeEnum == null){
//                return;
//            }
//            switch (componentTypeEnum){
//                case CONDITION:
//                    executables.add(createCondition((JSONObject) j, signalCenter));
//                    break;
//                case NODE:
//                    executables.add(createNode((JSONObject) j));
//                    break;
//                default:
//                    throw new TaException("反序列化失败，未找到componentType=【{}】的解析方式", componentTypeEnum);
//            }
//        });
//        return executables;
//    }

}
